﻿using AudioBooks.BookDetailsGroup;
using AudioBooks.Data;
using Books.SQLite;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using Services.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace AudioBooks.Controls
{
    public sealed partial class DownloadChapter : UserControl
    {

        List<DownloadOperation> downloadOperation;
        CancellationTokenSource cancellationToken;


       // private List<FileDownLoadComplete> filesDownload;
        private ObservableCollection<ChapterList> listChappterDownload;
        private string fileNameDownload = string.Empty;
        //private IBookDetailViewModel bookDetail
        //{
        //    get { return ServiceLocator.Current.GetInstance<IBookDetailViewModel>(); }
        //}

        public ObservableCollection<ChapterList> ListChappterDownload;
     

        private ChapterList dataContext;

        private ChapterList DataContextChapterList
        {
            get
            {
                if (dataContext == null)
                {
                    dataContext = (ChapterList)DataContext;
                }
                return dataContext;
            }
        }

        private string bookID;

        public DownloadChapter()
        {
            this.InitializeComponent();
            cancellationToken = new CancellationTokenSource();
            ListChappterDownload = new ObservableCollection<ChapterList>();
            DiscoverActiveDownloadsAsync();
        }

        public void Dispose()
        {
            if (cancellationToken != null)
            {
                cancellationToken.Dispose();
                cancellationToken = null;
            }
            GC.SuppressFinalize(this);
        }
        private RelayCommand<List<ChapterList>> downloadAll;
        public RelayCommand<List<ChapterList>> DownloadAll
        {
            get
            {
                if (downloadAll == null)
                    downloadAll = new RelayCommand<List<ChapterList>>(p => HandleDownloadAll(p));
                return downloadAll;
            }
        }
        private void HandleDownloadAll(List<ChapterList> listChapter)
        {
            if (cancellationToken == null)
                cancellationToken = new CancellationTokenSource();
            CheckFilesBeforeDownload(listChapter);
        }
        private async Task DiscoverActiveDownloadsAsync()
        {
            downloadOperation = new List<DownloadOperation>();
            IReadOnlyList<DownloadOperation> downloads = await BackgroundDownloader.GetCurrentDownloadsAsync(); ;

            try
            {
                downloads = await BackgroundDownloader.GetCurrentDownloadsAsync();
            }
            catch (Exception ex)
            {
                return;
            }

            // Log("Loading background downloads: " + downloads.Count);

            if (downloads.Count > 0)
            {
                List<Task> tasks = new List<Task>();
                foreach (DownloadOperation download in downloads)
                {
                    tasks.Add(HandleDownloadAsync(download, false));
                }
                await Task.WhenAll(tasks);
            }
        }
        private async void CheckFilesBeforeDownload(List<ChapterList> listChapter)
        {
            foreach (var m in listChapter)
            {
                var listData = ManagerFilesDownloadComplete.GetDataDownLoadFiles();
                if (listData == null)
                    ListChappterDownload.Add(m);
                else
                {
                    var checkFilesExits = listData.FirstOrDefault(k => k.FileName == m.chapter_no &&
                        k.BookId == App.BookIdSelect);
                    if (checkFilesExits == null)
                        ListChappterDownload.Add(m);
                }
            }
            if (ListChappterDownload.Count > 0)
            {
                foreach (var filesDownload in listChapter)
                    StartDownload(new Uri(filesDownload.audio_link), BackgroundTransferPriority.High, false);
                PanelDownload.Visibility = Windows.UI.Xaml.Visibility.Visible;
                ShowComplete.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
            }

        }

        private async void StartDownload(Uri source, BackgroundTransferPriority priority, bool requestUnconstrainedDownload)
        {
            bookID = App.BookIdSelect;
            fileNameDownload = source.Segments[source.Segments.Length-1];
            StorageFolder folder = null;
            var getFolderInfo = await ApplicationData.Current.LocalFolder.TryGetItemAsync(bookID);
            if (getFolderInfo == null)
                folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(bookID);
            else
                folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(bookID);

            StorageFile file = await folder.CreateFileAsync(fileNameDownload, CreationCollisionOption.ReplaceExisting);

            BackgroundDownloader downloader = new BackgroundDownloader();
            DownloadOperation download = downloader.CreateDownload(source, file);
            download.Priority = priority;
            downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
            if (!requestUnconstrainedDownload)
            {
                await HandleDownloadAsync(download, true);
                return;
            }
            List<DownloadOperation> requestOperations = new List<DownloadOperation>();
            requestOperations.Add(download);

            // If the app isn't actively being used, at some point the system may slow down or pause long running
            // downloads. The purpose of this behavior is to increase the device's battery life.
            // By requesting unconstrained downloads, the app can request the system to not suspend any of the
            // downloads in the list for power saving reasons.
            // Use this API with caution since it not only may reduce battery life, but it may show a prompt to
            // the user.
            UnconstrainedTransferRequestResult result;
            try
            {
                result = await BackgroundDownloader.RequestUnconstrainedDownloadsAsync(requestOperations);
            }
            catch (NotImplementedException)
            {
                return;
            }
            await HandleDownloadAsync(download, true);
        }
        private async Task HandleDownloadAsync(DownloadOperation download, bool start)
        {
            try
            {
                TextBlockProgress.Text = "Initializing....";
                ButtonPauseResume.IsEnabled = true;
                ButtonCancel.IsEnabled = true;
                downloadOperation.Add(download);
                Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress);
                if (start)
                {
                    // Start the download and attach a progress handler.
                    await download.StartAsync().AsTask(cancellationToken.Token, progressCallback);
                }
                else
                {
                    // The download was already running when the application started, re-attach the progress handler.
                    await download.AttachAsync().AsTask(cancellationToken.Token, progressCallback);
                }

                ResponseInformation response = download.GetResponseInformation();

                TextBlockProgress.Text = String.Format("Download Completed");
            }
            catch (TaskCanceledException)
            {
                TextBlockProgress.Text = "Canceled Download";
                DataContextChapterList.IsDownload = false;
                ButtonPauseResume.IsEnabled = false;
                ButtonCancel.IsEnabled = false;
                PanelDownload.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                ProgressBarDownload.Value = 0;
                ShowComplete.Visibility = Windows.UI.Xaml.Visibility.Visible;
            }
            catch (Exception ex)
            {
                return;
            }
            finally
            {
                downloadOperation.Remove(download);
            }
        }
        private void DownloadProgress(DownloadOperation download)
        {
            int progress = (int)(100 * ((double)download.Progress.BytesReceived / (double)download.Progress.TotalBytesToReceive));
            double percent = 0;
            if (download.Progress.TotalBytesToReceive > 0)
            {
                percent = download.Progress.BytesReceived * 100 / download.Progress.TotalBytesToReceive;
                ProgressBarDownload.Value = percent;
            }
            switch(download.Progress.Status)
            {
                case BackgroundTransferStatus.Running:
                    TextBlockProgress.Text = String.Format("{0} of {1} KB - {2}%", download.Progress.BytesReceived / 1024, download.Progress.TotalBytesToReceive / 1024, progress);
                    ButtonPauseResume.Content = "Pause";
                    break;
                case BackgroundTransferStatus.PausedByApplication:
                    TextBlockProgress.Text = "Download Pause";
                    ButtonPauseResume.Content = "Resume";
                    break;
                case BackgroundTransferStatus.PausedNoNetwork:
                    TextBlockProgress.Text = "Network Failed";
                    ButtonPauseResume.Content = "Resume";
                    break;
                case BackgroundTransferStatus.PausedCostedNetwork:
                    TextBlockProgress.Text = "Download Pause because of metered connection";
                    ButtonPauseResume.Content = "Resume";
                    break;
                case BackgroundTransferStatus.Error:
                    TextBlockProgress.Text = "Download Error";
                    ButtonPauseResume.Content = "Resume";
                    break;
            }

            if (percent >= 100)
            {
                if (DataContextChapterList == null)
                    return;
                if (DataContextChapterList.IsDownload)
                    return;
                DataContextChapterList.IsDownload = true;
                PanelDownload.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
                ShowComplete.Visibility = Windows.UI.Xaml.Visibility.Visible;
                ButtonPauseResume.IsEnabled = false;
                ButtonCancel.IsEnabled=false;
                download = null;
                ManagerFilesDownloadComplete.SaveDataFilesDownloadComplete(new FileDownLoadComplete() { IsDownLoadComplete = true, FileName = fileNameDownload, BookId = bookID });
            }
        }

        private void ButtonPauseResume_Click(object sender, RoutedEventArgs e)
        {
            if(ButtonPauseResume.Content.ToString()=="Pause")
            {
                try
                {
                    downloadOperation[0].Pause();
                }
                catch(InvalidOperationException ex)
                {

                }
            }
            else
            {
                try 
                {
                    downloadOperation[0].Resume();
                }
                catch(InvalidOperationException ex)
                { }
            }
        }

        private void ButtonCancel_Click(object sender, RoutedEventArgs e)
        {
            cancellationToken.Cancel();
            Dispose();
        }
    }
}